package com.hqd.utils.file;

import com.hqd.utils.file.filter.FileNameContainFilter;
import com.hqd.utils.file.filter.SuffixNameFilter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import javax.activation.MimetypesFileTypeMap;
import java.io.File;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class SimpleFileUtils {
    public final static String SUFFIX_NAME_SWF = ".swf";
    public final static String SUFFIX_NAME_MP4 = ".mp4";
    public final static String SUFFIX_NAME_AVI = ".avi";
    public final static String SUFFIX_NAME_WMV = ".wmv";
    public final static String SUFFIX_NAME_FLV = ".flv";
    public final static String SUFFIX_NAME_TS = ".ts";
    public final static String SUFFIX_NAME_TXT = ".txt";
    public final static String SUFFIX_NAME_M3U8 = ".m3u8";

    public final static String FILE_SEPARATOR = File.separator;

    /**
     * 获取时间范围内指定后缀文件
     *
     * @param file    目标文件
     * @param endTime 截止时间
     * @param day     间隔天数
     * @param suffixs 指定后缀
     * @return
     */
    public static List<File> getFilesInTime(File file, Date endTime, int day, String... suffixs) {
        if (file == null || endTime == null) {
            return null;
        }
        if (day < 0) {
            return null;
        }

        List<File> files = new ArrayList<>();
        if (isNonExists(file)) {
            return files;
        }
        if (file.isHidden()) {
            return files;
        }

        long time = endTime.getTime();
        if (file.isFile()) {
            if (ArrayUtils.isNotEmpty(suffixs)) {
                if (!ArrayUtils.contains(suffixs, getFileSuffix(file))) {
                    return files;
                }
            }
            long modified = file.lastModified();
            long diff = ChronoUnit.DAYS.between(Instant.ofEpochMilli(modified), Instant.ofEpochMilli(time));
            if (diff <= day) {
                files.add(file);
            }
        } else {
            for (File f : file.listFiles()) {
                files.addAll(getFilesInTime(f, endTime, day, suffixs));
            }
        }
        return files;
    }

    public static void addPrefixDirFilesName(File file, String prefix, String searchName) {
        if (StringUtils.isBlank(prefix)) {
            return;
        }
        if (isDir(file)) {
            File[] files = file.listFiles(new FileNameContainFilter(searchName));
            for (File f : files) {
                addPrefixFileName(f, prefix);
            }
        }
    }

    /**
     * 文件添加名称(头添加)
     *
     * @param file   目标文件
     * @param prefix 前缀
     */
    public static boolean addPrefixFileName(File file, String prefix) {
        if (StringUtils.isBlank(prefix)) {
            return false;
        }
        if (isExists(file)) {
            String newFileName = prefix + file.getName();
            File newFile = new File(file.getParent(), newFileName);
            return file.renameTo(newFile);
        }
        return false;
    }

    /**
     * 替换文件夹下所有文件
     *
     * @param file   目标文件夹
     * @param oldStr 旧字符串
     * @param newStr 新字符串
     */
    public static void replaceDirFilesName(File file, String oldStr, String newStr) {
        replaceDirFilesName(file, oldStr, newStr, false);
    }

    /**
     * 替换文件夹下所有文件
     *
     * @param file         目标文件夹
     * @param oldStr       旧字符串
     * @param newStr       新字符串
     * @param isContainDir 是否修改文件夹
     */
    public static void replaceDirFilesName(File file, String oldStr, String newStr, boolean isContainDir) {
        if (StringUtils.isBlank(oldStr)) {
            return;
        }
        if (isDir(file)) {
            File[] files = file.listFiles();
            for (File f : files) {
                if (f.isFile()) {
                    replaceFileName(f, oldStr, newStr);
                } else {
                    if (isContainDir) {
                        replaceFileName(f, oldStr, newStr);
                    }
                }
            }
        }
    }

    /**
     * 替换文件名称
     *
     * @param file   目标文件
     * @param oldStr 旧字符串
     * @param newStr 新字符串
     */
    public static boolean replaceFileName(File file, String oldStr, String newStr) {
        if (StringUtils.isBlank(oldStr)) {
            return false;
        }
        if (isExists(file)) {
            String newFileName = StringUtils.replaceOnce(file.getName(), oldStr, newStr);
            File newFile = new File(file.getParent(), newFileName);
            return file.renameTo(newFile);
        }
        return false;
    }

    /**
     * 添加文件夹下所有文件后缀
     *
     * @param file   目标文件夹
     * @param suffix 后缀名
     */
    public static void addDirFilesSuffix(File file, String suffix) {
        if (StringUtils.isBlank(suffix)) {
            return;
        }
        if (isDir(file)) {
            File[] files = file.listFiles();
            for (File f : files) {
                addFileSuffix(f, suffix);
            }
        }
    }

    /**
     * 添加后缀
     *
     * @param file   目标文件
     * @param suffix 后缀名
     */
    public static boolean addFileSuffix(File file, String suffix) {
        if (StringUtils.isBlank(suffix)) {
            return false;
        }
        if (isFile(file)) {
            if (!StringUtils.contains(file.getName(), ".")) {
                return alertFileSuffix(file, suffix);
            }
        }
        return false;
    }

    /**
     * 修改文件夹下所有的匹配文件
     *
     * @param file      目标文件夹
     * @param oldSuffix 旧后缀名
     * @param newSuffix 新后缀名
     */
    public static void alertDirFilesSuffix(File file, String oldSuffix, String newSuffix) {
        if (StringUtils.isBlank(oldSuffix) || StringUtils.isBlank(newSuffix)) {
            return;
        }
        if (isDir(file)) {
            File[] files = file.listFiles(new SuffixNameFilter(oldSuffix));
            for (File f : files) {
                if (matchSuffix(f, oldSuffix)) {
                    alertFileSuffix(f, newSuffix);
                }
            }
        }
    }

    /**
     * 修改文件后缀名
     *
     * @param file      目标文件
     * @param newSuffix 新后缀名
     */
    public static boolean alertFileSuffix(File file, String newSuffix) {
        if (StringUtils.isBlank(newSuffix)) {
            return false;
        }
        if (isFile(file)) {
            if (StringUtils.startsWith(newSuffix, ".")) {
                String fileName = getFileName(file) + newSuffix;
                File newFile = new File(file.getParent(), fileName);
                return file.renameTo(newFile);
            }
        }
        return false;
    }

    /**
     * 获取文件名称（不包含后缀）
     *
     * @param file 目标文件
     * @return
     */
    public static String getFileName(File file) {
        if (isExists(file)) {
            int last = file.getName().lastIndexOf(".");
            if (last == -1)
                return file.getName();
            return file.getName().substring(0, last);
        }
        return null;
    }

    /**
     * 获取文件后缀名
     *
     * @param file 目标文件
     * @return
     */
    public static String getFileSuffix(File file) {
        int last = file.getName().lastIndexOf(".");
        String suffix = "";
        if (last != -1) {
            suffix = file.getName().substring(last);

        }
        return suffix;
    }

    /**
     * 匹配后缀名
     *
     * @param file   目标文件
     * @param suffix 后缀名
     * @return
     */
    public static boolean matchSuffix(File file, String suffix) {
        if (StringUtils.isNotBlank(suffix)) {
            if (suffix.startsWith(".")) {
                return StringUtils.endsWithIgnoreCase(file.getName(), suffix);
            }
        }
        return false;
    }

    /**
     * 文件名是否包含字符串
     *
     * @param file       目标文件
     * @param searchStr  关键字
     * @param ignoreCase 是否忽略大小写
     * @return
     */
    public static boolean fileNameContainsStr(File file, String searchStr, boolean ignoreCase) {
        if (ignoreCase) {
            return StringUtils.containsIgnoreCase(file.getName(), searchStr);
        } else {
            return StringUtils.contains(file.getName(), searchStr);
        }
    }

    /**
     * 到指定目录搜索文件
     *
     * @param file         查找路径
     * @param searchStr    搜索字符串
     * @param isRecursion  是否递归
     * @param isContainDir 是否包含文件夹
     * @param ignoreCase   忽略大小写
     * @return
     */

    public static List<File> searchFile(File file, String searchStr, boolean isRecursion,
                                        boolean isContainDir, boolean ignoreCase) {
        List<File> fileList = new ArrayList<>();
        if (isNonExists(file) || StringUtils.isBlank(searchStr)) {
            return fileList;
        }
        if (file.isFile()) {
            if (fileNameContainsStr(file, searchStr, ignoreCase)) {
                fileList.add(file);
            }
            return fileList;
        } else {
            if (isContainDir) {
                if (fileNameContainsStr(file, searchStr, ignoreCase)) {
                    fileList.add(file);
                }
            }
        }
        //遍历所属文件
        for (File f : file.listFiles()) {
            if (f.isFile()) {
                fileList.addAll(searchFile(f, searchStr, isRecursion, isContainDir, ignoreCase));
            } else {
                if (isRecursion) {
                    fileList.addAll(searchFile(f, searchStr, true, isContainDir, ignoreCase));
                }
            }
        }
        return fileList;
    }

    public static boolean isDir(File file) {
        if (!isExists(file)) {
            return false;
        }
        return file.isDirectory() ? true : false;
    }

    public static boolean isFile(File file) {
        if (isNonExists(file)) {
            return false;
        }
        return file.isFile() ? true : false;
    }

    public static boolean isNonExists(File file) {
        return !isExists(file);
    }

    /**
     * 判断文件是否存在
     *
     * @param file 目标文件
     * @return
     */
    public static boolean isExists(File file) {
        if (file == null || !file.exists()) {
            return false;
        }
        return true;
    }

    public static List<File> searchFile(File file, String fileName, boolean isRecursion, boolean ignoreCase) {
        return searchFile(file, fileName, isRecursion, false, ignoreCase);
    }


    public static List<File> searchFile(File file, String fileName, boolean isRecursion) {
        return searchFile(file, fileName, isRecursion, false, true);
    }

    public static List<File> searchFile(File file, String fileName) {
        return searchFile(file, fileName, false, false, true);
    }

    /**
     * 获取文件类型
     *
     * @param fileUrl 文件url
     */
    public static String getContentType(String fileUrl) {
        String contentType = null;
        try {
            contentType = new MimetypesFileTypeMap().getContentType(new File(fileUrl));
        } catch (Exception e) {
            return null;
        }
        return contentType;
    }
}
